﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace TestMonkey.Core
{
    /// <summary>
    /// Basic plug-in for templates
    /// </summary>
    public abstract class TemplateProcessor
    {
        protected TemplateProcessor()
        {
            CreateMode = Core.CreateMode.Overwrite;
        }

        private TestBuilder m_Parent;

        internal void Initialize(TestBuilder parent)
        {
            m_Parent = parent;
        }

        public virtual bool ShouldRun(Type type)
        {
            return true;
        }

        public Setup Setup
        {
            get { return m_Parent.Setup; }
        }

        public CreateMode CreateMode { get; set; }

        public void ProcessTemplate(Type type)
        {
            var template = LoadTemplate(TemplateFileName(type), true);

            OnProcessTemplate(type, template);

            WriteFile(type, TemplatePartName(), template);
        }

        protected virtual void OnProcessTemplate(Type type, StringBuilder template)
        {
            template.Replace("$TestNamespace$", Setup.TestNamespace);
            template.Replace("$TestClassName$", Setup.GetTestClassName(type));
            template.Replace("$ClassName$", type.Name);
            template.Replace("$ClassNamespace$", type.Namespace);

            template.Replace("$TestName$", GetType().Name);

        }


        public virtual string TemplateFileName(Type type)
        {
            return GetType().Name;
        }

        public virtual string TemplatePartName()
        {
            return GetType().Name;
        }

        protected StringBuilder LoadTemplate(string file, bool allowDefault)
        {
            StringBuilder template = null;
            foreach (var path in Setup.TemplatePaths)
            {
                template = LoadTemplate(path, file);
                if (template != null)
                    return template;
            }

            if (allowDefault)
            {
                foreach (var path in Setup.TemplatePaths)
                {
                    template = LoadTemplate(path, "Default");
                    if (template != null)
                        return template;
                }
            }

            throw new ArgumentException("Template " + file + " does not exist");
        }

        StringBuilder LoadTemplate(string templateFolder, string file)
        {
            var rootFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            var fullPath = Path.Combine(rootFolder, templateFolder, file + ".template");
            if (!File.Exists(fullPath))
                return null;

            var template = new StringBuilder(File.ReadAllText(fullPath));
            return template;
        }

        protected void WriteFile(Type type, string part, StringBuilder contents)
        {
            var file = Setup.GetTargetFile(type, part);
            if (file.Exists)
            {
                if (CreateMode == CreateMode.Overwrite)
                {
                    if (File.ReadAllText(file.FullName) != contents.ToString())
                    {
                        Console.WriteLine("\tUpdating " + file.FullName.Substring(Setup.TargetFolder.Length + 1));
                        File.WriteAllText(file.FullName, contents.ToString());
                    }
                }
            }
            else
            {
                file.Directory.Create();
                File.WriteAllText(file.FullName, contents.ToString());
                Console.WriteLine("\tCreating " + file.FullName.Substring(Setup.TargetFolder.Length + 1));
            }
        }




    }

}